Repository navigation
Conversation
|
@MarcZX10 thanks, reviewed at 7ae84d2. The validator, the shell-free launch on each OS (
There is also a small conflict with #12848 in |
7ae84d2 to
bce7cb8
Compare
Re-checked — new head bce7cb8, both requests addressedBoth points were fair: nothing bounded repeated calls, and What I ran
Changes (15 new commits, each with its test)
Results
Negative control
Not verified
I will re-run the checks on any new head and say so here. |
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Windows run of this head (
AI-assisted: yes (Claude Code). |
bce7cb8 to
d0a4124
Compare
d0a4124 to
76ce444
Compare
libSceSystemService/CMakeLists.txt: keep main's system_service_host_locale interface library and add it to this branch's link line next to SDL2-static. docs/dev/ENVIRONMENT.md: keep main's ANYPS5_LANGUAGE row and this branch's ANYPS5_OPEN_URLS row.
…and credentials A file URL, an address with credentials and one with a space start nothing.
HostMessageBoxConfirmation shows the whole address (wrapped every 96 characters for display only) in a warning box with Cancel as the default for Return and Escape. SDL_ShowMessageBox needs no initialised video subsystem and no particular thread on Windows and X11, and the macOS implementation dispatches to the main queue. When SDL cannot show a box, for example with no display, the answer is no. libSceSystemService now links SDL2-static for this.
…answer The wrapped text keeps the whole address and no line over 96 characters. On Linux, with DISPLAY and WAYLAND_DISPLAY removed, the message box cannot be shown and the confirmation answers no without opening anything.
…r on the host After the sourced argument checks (null, 6015 bytes, http:, https: or psno:), the call now consults ANYPS5_OPEN_URLS. Unset, empty or never keep today's EOPNOTSUPP result. With ask or always, a URL that passes the host validator is confirmed and launched through the injectable backends and the call returns 0; a declined, rejected or failed launch still returns EOPNOTSUPP. The launch is serialised so two guest threads never stack confirmation boxes. An invalid ANYPS5_OPEN_URLS value throws an error naming the variable at the first call that gets past the argument checks.
With injected backends: unset, empty and never keep EOPNOTSUPP and touch neither backend; ask confirms before launching and a declined or failed launch returns EOPNOTSUPP; always launches without asking; invalid addresses and the sourced 0x80a10003, 0x80a10007 and 0x80a10008 results reach neither backend in any mode; a bogus variable throws naming it after the argument checks.
Adds the variable to the environment reference: never, ask or always, with unset and empty keeping the current failing result.
Lists the three modes, why always is discouraged, what a missing display does, the accepted address forms and the refusals, and how each host starts the browser.
The silent-stub entry for sceSystemServiceLaunchWebBrowser now states the failure applies when ANYPS5_OPEN_URLS is unset, empty or never.
…bBrowser The result is the default one; ANYPS5_OPEN_URLS=ask or always changes it for addresses the host opens.
…e browser launch The native result for a launched browser is unknown, and the host accepts fewer addresses than the console's own checks.
Only the Linux opener is exercised; the Windows and macOS backends, the macOS main-queue dispatch and Wayland without Xwayland are reasoned from the SDL and platform documentation.
sceWebBrowserDialogOpen does not open anything on the host because no public source gives the parameter layout or the URL offset.
OpenUrlGate runs OpenUrlOnHost behind a try-lock: a caller that arrives while a confirmation box or a launch is in progress gets Busy at once instead of queuing another dialog behind it. never still makes no backend call and an invalid address is rejected before the lock is touched. The gate takes an injectable clock for the limits that follow. Nothing calls it yet.
While a confirmation is blocked, other callers for the same and distinct addresses, in ask and always, get Busy without a second dialog or launch; a never call and an invalid address are answered without touching the lock; 1000 never calls make no backend call.
…nute Every confirmation shown in ask and every launch in always counts as an attempt in a sliding 60 second window kept by the shared gate. A fourth attempt inside the window returns Limited without a dialog or a launch, whatever the address, and the window empties as attempts age out of it by the injected clock.
…unts Three attempts pass in ask and in always, then 1000 same and distinct addresses are limited with no further dialog or launch; the window opens again exactly 60 seconds after its oldest attempt. Rejected addresses do not count, failed launches do.
A declined confirmation suppresses every further prompt and launch, for any address, until 600 seconds later by the injected clock; those calls return Suppressed at once and do not count against the per-minute cap. The pause is bounded, not for the whole session, so a user who cancelled once can still open a link they ask for later without restarting the game.
After a decline every same or distinct address is suppressed in ask and always with no dialog or launch, until exactly 600 seconds later; repeated Cancel shows one box per interval; suppressed calls do not use up the per-minute attempts.
The fake clock, launcher and confirmation move out of the limits test so the exported-call tests can reuse them. No assertion changes.
…the shared gate All guest threads and all addresses now share one OpenUrlGate: callers that arrive during a dialog or launch, repeats after a Cancel and more than three attempts a minute return the existing EOPNOTSUPP without touching a backend. The mutex that queued callers is gone. The test hook takes the clock too and resets the gate; the existing exported-call test advances a fake clock between calls so its sequence is unaffected by the limits.
With counting fakes and a fake clock: repeated Cancel on the same and distinct addresses shows one box until the cooldown ends; more than three launches a minute are refused and resume after the window; 1000 never calls reach no backend; sixteen concurrent callers during an open confirmation get EOPNOTSUPP and add no second box.
Each accepted launch left a child and a detached wait thread for as long as the opener lived. The launcher now counts running openers, shared with the wait threads so it survives the launcher, and refuses a third until one exits. The gate's three a minute still apply on top.
A blocking opener script holds two launches open: a third and twenty more are refused and start nothing; once the first two exit a launch succeeds again.
…esses ask shows the address before anything opens; always opens whatever http or https host the game names, including localhost and a router's page.
Busy callers are refused, three attempts a minute, and ten minutes of silence after Cancel; refused requests fail like the default.
The busy refusal, the attempt cap, the cooldown after Cancel and the opener bound are not measured on the console.
The usage text promises three attempts, 60 seconds and 10 minutes; the limits test derived its sequences from the constants, so changing a constant moved test and code together. The values are now asserted literally.
b8bd072 to
737ac71
Compare
✅ AMD GPU test: passedPR head
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (6, not counted against this PR)Validated but not compared (64, not in the main baseline's validation pass)Validation IDs already present on main (8 IDs in 677 tests)Skipped (10)ReproduceAutomated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
What
sceSystemServiceLaunchWebBrowser(one URI argument; the null, 6015-byte andhttp:/https:/psno:checks already on main come from a measured library reading) returnedEOPNOTSUPPfor every valid address, so a title that asks for its browser (PPSA76677 falls back to a QR code) got nothing. It can now open the address in the host's default browser, opt-in throughANYPS5_OPEN_URLS=never|ask|always. Unset, empty andneverkeep today's result exactly.Scope note: the requested target was
libSceWebBrowserDialog, but no public source gives the layout of thesceWebBrowserDialogOpenparameter or the offset of its URL field (OpenOrbis-PS4-Toolchain @ 0a1aaf9dd4a92695538bdeb09fb056d06dd11725include/orbis/WebBrowserDialog.hdeclares every function with no parameters; shadPS4 @ f68923fe807f657348e6719ce658bcbd0a2b1c72webbrowserdialog.cpptakes none). The dialog is unchanged except for one debt line saying so. The store and profile dialogs carry ids, not URLs.Design (all host-side, injected behind interfaces):
ValidateHostUrl: onlyhttp://andhttps://, at most 2048 bytes, RFC 3986 characters only (so no control characters, spaces, non-ASCII or look-alike Unicode hosts), percent escapes well formed and not decoding to a control character, no credentials (user@,good.com@evil.com), non-empty host (DNS names or IPv6 literals), port 1 to 65535.IUrlLauncherandIUrlConfirmation;OpenUrlOnHostapplies the mode. An address that fails the validator reaches neither backend in any mode.posix_spawnpofxdg-open(Linux) or/usr/bin/open(macOS) with the address as a single argv element and stdio on /dev/null, never a shell;ShellExecuteWon Windows after revalidating the address. Each backend refuses anything that is not a valid URL by itself.SDL_ShowMessageBox(SDL2-static is now linked into libSceSystemService) showing the whole address, Cancel as the default for Return/Escape; no display means no. It does not use or stack on the overlay dialogs of feat(overlay): show PS5 system dialogs as real PC dialogs #12379 (no shared files; the conceptual overlap is "a host dialog"). A mutex serialises launches so two guest threads never stack boxes.EOPNOTSUPP. An invalidANYPS5_OPEN_URLSthrows naming the variable at the first call past the argument checks.Commits (22): validator + test; mode parsing + test; interfaces/policy + test; POSIX backend + test; Windows backend; POSIX launcher revalidation + test; SDL confirmation + test; wiring + test; env reference; usage; five debt statements (one per commit).
Overlap with open PRs: none edit the same lines. #12848 and #12752 also add rows/paragraphs to
docs/dev/ENVIRONMENT.mdanddocs/user/USAGE.mdand touch libSceSystemService (language and date format variables); #12285 touches libSceSystemServiceExport.cppelsewhere. #12379 toucheslibSceMsgDialogand other CMake files, not these.Tested
Linux x86_64, g++ 12, archive build with the host CPU gate patched (
run_tests.sh).guest_system_service_open_url(new),guest_system_service,guest_system_service_language,guest_system_service_time_zone,guest_system_service_usb_storage,guest_system_service_app_title_id_{known,long,missing},loadexec_arguments,guest_system_exit,guest_system_exit_parameters: 11/11 passed.EOPNOTSUPPforhttp:,https:,psno:and the sourced error codes).ctest): 24 mutations, all aborted the test: credentials check removed, control-escape check removed, port upper bound, port zero, scheme prefix loosened, length limit raised, non-ASCII allowed, space allowed, empty host allowed, IPv6 characters unchecked, unknown mode returning never, variable name dropped from the message, policy without validation,askskipping the question,alwaysasking,neverlaunching, launcher failure ignored, POSIX launcher without revalidation, POSIX launcher spawningsh, POSIX launcher reporting failure after spawn, confirmation wrap off, confirmation truncating, confirmation answering yes on SDL failure, wiring ignoring the mode, wiring always returning 0, wiring ignoring the environment, null-argument code changed. The failing line inside the test was not extracted (assertions useabort), so "intended case" is by construction of each mutation, not by line.tools/check_conventions.py --base upstream/main,git diff --check,test_public_headers.py --audit-only,env_reference.py --checkall clean on the final rebased head.x86_64-w64-mingw32-g++ -fsyntax-onlyon the Windows backend.NOT RUN: Windows (ShellExecuteW backend and SDL box), macOS (
openbackend, main-queue dispatch of the box), any real launch of a browser or a real message box (tests use a recording script and fakes; the Linux no-display test only proves the box answers no without a display), a Wayland-only session, a console, a title (PPSA76677). No test rebuild after the final two rebases (my files and the tests are unchanged). The unfixed code was not run against the new tests beyond the baseline list above.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)